package com.ip.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.HashMap;
import java.util.Random;
/**
 * 滑块验证码工具类（严格遵循55x45滑块尺寸，Y轴固定55px）
 */
public class RandomValidateCodeUtil {
    private static final Logger log = LoggerFactory.getLogger(RandomValidateCodeUtil.class);

    // 严格遵循项目规范的常量定义
    public static final int TARGET_WIDTH = 55;   // 滑块宽度（固定55px）
    public static final int TARGET_HEIGHT = 45;  // 滑块高度（固定45px）
    public static final int FIXED_Y_HEIGHT = 55; // Y轴高度固定55px
    private static final int CIRCLE_R = 8;       // 滑块圆角半径
    private static final int R1 = 4;             // 形状计算参数
    private static final String[] IMAGE_FILES = {"11.jpg", "22.jpg"}; // 图片资源
    private static final int STANDARD_IMAGE_WIDTH = 300;  // 标准大图宽度（前后端统一）
    private static final int STANDARD_IMAGE_HEIGHT = 180; // 标准大图高度（前后端统一）

    /**
     * 生成滑块验证码（严格遵循尺寸规范）
     */
    public static HashMap<String, Object> createImage() {
        HashMap<String, Object> resultMap = new HashMap<>();
        try {
            // 加载图片并统一缩放至标准尺寸（300x180）
            BufferedImage oriImage = getScaledImage();
            if (oriImage == null) {
                log.warn("图片加载失败，使用标准默认图");
                oriImage = createStandardDefaultImage();
            }

            Random random = new Random();
            // 计算X轴随机坐标（确保在有效范围内）
            int maxX = STANDARD_IMAGE_WIDTH - TARGET_WIDTH; // 300-55=245
            int widthRandom = random.nextInt(Math.max(1, maxX)); // X轴范围：0-245
            int heightRandom = FIXED_Y_HEIGHT; // Y轴固定55px（项目规范）

            log.info("标准图尺寸: {}x{}, 滑块坐标: ({}, {})",
                    STANDARD_IMAGE_WIDTH, STANDARD_IMAGE_HEIGHT, widthRandom, heightRandom);

            // 创建滑块图片（严格55x45）
            BufferedImage targetImage = new BufferedImage(TARGET_WIDTH, TARGET_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR);
            cutByTemplate(oriImage, targetImage, getBlockData(), widthRandom, heightRandom);

            // 返回标准格式数据（前后端尺寸完全一致）
            resultMap.put("success", true);
            resultMap.put("token", generateToken());
            resultMap.put("bigImage", getImageBASE64(oriImage));
            resultMap.put("smallImage", getImageBASE64(targetImage));
            resultMap.put("imageWidth", STANDARD_IMAGE_WIDTH);  // 标准宽度300
            resultMap.put("imageHeight", STANDARD_IMAGE_HEIGHT); // 标准高度180
            resultMap.put("xWidth", widthRandom);
            resultMap.put("yHeight", heightRandom);

        } catch (Exception e) {
            log.error("生成滑块验证码异常", e);
            resultMap.put("success", false);
            resultMap.put("message", "生成验证码失败: " + e.getMessage());
        }
        return resultMap;
    }

    /**
     * 加载图片并缩放至标准尺寸（300x180）
     */
    private static BufferedImage getScaledImage() {
        try {
            // 随机选择图片
            Random random = new Random();
            String selectedImage = IMAGE_FILES[random.nextInt(IMAGE_FILES.length)];

            // 从资源加载
            try (InputStream imageStream = RandomValidateCodeUtil.class.getResourceAsStream("/static/" + selectedImage)) {
                if (imageStream == null) {
                    log.warn("图片文件不存在: {}", selectedImage);
                    return null;
                }

                BufferedImage originalImage = ImageIO.read(imageStream);
                // 缩放至标准尺寸（300x180）
                BufferedImage scaledImage = new BufferedImage(
                        STANDARD_IMAGE_WIDTH,
                        STANDARD_IMAGE_HEIGHT,
                        BufferedImage.TYPE_INT_RGB
                );
                Graphics2D g = scaledImage.createGraphics();
                g.drawImage(originalImage, 0, 0, STANDARD_IMAGE_WIDTH, STANDARD_IMAGE_HEIGHT, null);
                g.dispose();
                return scaledImage;
            }
        } catch (IOException e) {
            log.error("图片缩放失败", e);
            return null;
        }
    }

    /**
     * 创建标准默认图（300x180）
     */
    private static BufferedImage createStandardDefaultImage() {
        BufferedImage image = new BufferedImage(STANDARD_IMAGE_WIDTH, STANDARD_IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = image.createGraphics();

        // 绘制渐变背景
        GradientPaint gradient = new GradientPaint(
                0, 0, new Color(102, 126, 234),
                STANDARD_IMAGE_WIDTH, STANDARD_IMAGE_HEIGHT, new Color(118, 75, 162)
        );
        g2d.setPaint(gradient);
        g2d.fillRect(0, 0, STANDARD_IMAGE_WIDTH, STANDARD_IMAGE_HEIGHT);
        g2d.dispose();
        return image;
    }

    /**
     * 切割滑块（严格按55x45尺寸）
     */
    private static void cutByTemplate(BufferedImage oriImage, BufferedImage targetImage,
                                      int[][] templateImage, int x, int y) {
        // 强制校验尺寸（确保符合规范）
        if (targetImage.getWidth() != TARGET_WIDTH || targetImage.getHeight() != TARGET_HEIGHT) {
            throw new IllegalArgumentException("滑块尺寸必须为" + TARGET_WIDTH + "x" + TARGET_HEIGHT);
        }

        int[][] matrix = new int[3][3];
        int[] values = new int[9];

        for (int i = 0; i < TARGET_WIDTH; i++) {
            if (x + i >= oriImage.getWidth()) break;

            for (int j = 0; j < TARGET_HEIGHT; j++) {
                if (y + j >= oriImage.getHeight()) break;

                int rgb = templateImage[i][j];
                int rgbOri = oriImage.getRGB(x + i, y + j);

                if (rgb == 1) {
                    targetImage.setRGB(i, j, rgbOri);
                    // 原图缺口添加模糊效果
                    readPixel(oriImage, x + i, y + j, values);
                    fillMatrix(matrix, values);
                    oriImage.setRGB(x + i, y + j, avgMatrix(matrix));
                } else {
                    // 滑块背景透明
                    targetImage.setRGB(i, j, rgbOri & 0x00ffffff);
                }
            }
        }
    }

    /**
     * 生成滑块形状（55x45固定尺寸）
     */
    private static int[][] getBlockData() {
        int[][] data = new int[TARGET_WIDTH][TARGET_HEIGHT];
        double x2 = TARGET_WIDTH - CIRCLE_R;
        double h1 = CIRCLE_R + Math.random() * (TARGET_WIDTH - 3 * CIRCLE_R - R1);
        double po = Math.pow(CIRCLE_R, 2);
        double xBegin = TARGET_WIDTH - CIRCLE_R - R1;
        double yBegin = TARGET_HEIGHT - CIRCLE_R - R1;

        for (int i = 0; i < TARGET_WIDTH; i++) {
            for (int j = 0; j < TARGET_HEIGHT; j++) {
                double d2 = Math.pow(j - 2, 2) + Math.pow(i - h1, 2);
                double d3 = Math.pow(i - x2, 2) + Math.pow(j - h1, 2);
                data[i][j] = ((j <= yBegin && d2 < po) || (i >= xBegin && d3 > po)) ? 0 : 1;
            }
        }
        return data;
    }

    // 辅助方法：图片转Base64
    private static String getImageBASE64(BufferedImage image) throws IOException {
        try (ByteArrayOutputStream bao = new ByteArrayOutputStream()) {
            ImageIO.write(image, "png", bao);
            return Base64.getEncoder().encodeToString(bao.toByteArray());
        }
    }

    // 生成唯一token
    private static String generateToken() {
        return System.currentTimeMillis() + "_" + new Random().nextInt(10000);
    }

    // 像素处理辅助方法（确保缺口模糊效果正确）
    private static void readPixel(BufferedImage img, int x, int y, int[] pixels) {
        int xStart = x - 1;
        int yStart = y - 1;
        int current = 0;
        for (int i = xStart; i < 3 + xStart; i++) {
            for (int j = yStart; j < 3 + yStart; j++) {
                int tx = Math.max(0, Math.min(i, img.getWidth() - 1));
                int ty = Math.max(0, Math.min(j, img.getHeight() - 1));
                pixels[current++] = img.getRGB(tx, ty);
            }
        }
    }

    private static void fillMatrix(int[][] matrix, int[] values) {
        int filled = 0;
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                matrix[i][j] = values[filled++];
            }
        }
    }

    private static int avgMatrix(int[][] matrix) {
        int r = 0, g = 0, b = 0;
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (j == 1) continue;
                Color c = new Color(matrix[i][j]);
                r += c.getRed();
                g += c.getGreen();
                b += c.getBlue();
            }
        }
        return new Color(r / 8, g / 8, b / 8).getRGB();
    }
}